MediaLiveとNLBでRTMPSによるストリーミングをしてみた
はじめに
清水です。AWS Media Blogで「AWSでRTMPSストリーミングを行う」という大変興味深いエントリがポストされていました。
AWS Elemental MediaLiveとAWS Elemental MediaPackageを利用したライブ動画配信の構成なのですが、Streaming Software(OBS Studio)からAWSへの入力をRTMPSでできるようにしています。
RTMPS Streaming with AWS | AWS Media Blog
AWS Elemental MediaLiveでは一般的なRTMPでのライブソースの入力に対応しています。YouTube LiveやFacebook Live、Twitchなど多くの動画配信プラットフォームと同じ形式ですね。(なお、MediaLiveでは一般的なRTMPでの入力方式であるRTMP pushのほか、RTMP pullについてもサポートしています。)
ところで、RTMPにはSSL/TLSを用いて暗号化を行うRTMPSという拡張仕様があります。動画配信プラットフォームの多くではこのRTMPS形式にも対応していたのですが、MediaLiveのRTMP入力形式ではRTMPのみの対応でRTMPSには非対応という状況でした。(ただし、MediaLiveでは暗号化が一切できないわけではなく、他プロトコルを使ったりAWS Elemental MediaConnectと連携するなどといった手段で入力ストリームの暗号化には対応していました。)
今回「MediaLive自体がRTMPSでの入力に対応した」というわけではないのですが、AWS Media BlogのエントリではMediaLive Inputの前段にNLB (Network Load Balancer)を配置、Streaming SoftwareからのRTMPS通信をNLBでTLS終端させてMediaLiveにRTMPで渡す構成を紹介しています。個人的にRTMPSがRTMPをSSL/TLSで暗号化したもの、という理解はしていたのですが、NLBでTLS終端させるという手段があったか!と、このAWS Media Blogのエントリを読んで驚愕しました。本エントリでは、この「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」という構成を実際に検証してみたのでまとめてみたいと思います。
Architecture Deep Dive
アーキテクチャの概要は冒頭で引用したAWS Media Blogのエントリの通りとなりますが、この構成についてもう少し深追いしてみます。NLBでRTMPSのTLSを終端させてRTMPとしてMediaLiveの入力とする、ということに変わりはないのですが、NLBの配置やMediaLive Inputに用いるVPCの構成についてもまとめると以下のようになります。
Streaming SoftwareからのRTMPSの入力はインターネットを介して行われる想定です。そのため、Public Subnetに配置したNLBでRTMPSの入力を受け付けます。NLBでTLSを終端させたあとの、MediaLiveへのInputはインターネットを介すべきではありません。MediaLiveのInputリソースはVPC Mode(VPC Input)で作成します。このMediaLiveのVPC ModeのInput(VPC Input)についてはインターネットへの経路は必要ないため、Private Subnetに配置することとしました。このPrivate SubnetにはNAT Gatewayへの経路もなく、インターネットとの通信は不可の状況です。
MediaLiveのOutput以降については、RTMPS入力とは分離して設計することが可能であるため、通常のRTMP入力などと同じようにMediaPackageのほか、MediaLiveで利用できる任意のOutputが選択可能となります。
Streaming SoftwareからNLBへの接続の部分についても確認しておきましょう。NLBでのTLS終端のため、独自ドメインならびにSSL/TLS証明書を準備します。Streaming Softwareからはこの独自ドメイン(例としてlive.example.com
)に対してRTMPSで映像を打ち上げます。この独自ドメインlive.example.com
にはDNSでNLBへのレコードを登録しておきます。またNLBにはlive.example.com
に対応した証明書を設定しておき、live.example.com
で接続した際のTLS終端ができるようにしておきます。ここで証明書の発行、管理にはAWS Certificate Manager (ACM)を使用し、またドメインについてのDNS管理にはAmazon Route 53を使う、という構成になっています。
MediaLiveとNLBでRTMPSによるストリーミング環境を構築する
では実際に上記アーキテクチャを実装していき、MediaLiveとNLBによるRTMPSストリーミングをやってみたいと思います。今回は動作検証ということで、MediaLiveはSINGLE_PIPELINEオプションを使用した冗長性を持たない構成としました。Input Failoverについても設定せず、1つのChannelに1つのInputのみが紐付いている状態です。またNLBについても冗長性を持たせず、1つのAZのみを使用する構成としています。
VPCならびにサブネットの詳細構成は以下となります。今回、PrivateSubnetはNAT Gatewayなどへの経路を持たず、インターネットへの接続不可のサブネットとしています。また本エントリではVPCやサブネットの作成についての手順については省略し、Security Groupの作成から進めます。
Security Groupの作成
まずはSecurity Groupの作成から進めます。今回の構成でVPC内に配置するリソースはNLBとMediaLive VPC Inputがありますが、NLBについてはSecurity Groupを設定できません。後続のリソース、今回であればMediaLiveのVPC InputへアタッチするSecurity Groupで通信を制御する必要があります。またNLBを含んだ構成でのSecurity Groupルール設定についてはいくつか考慮する必要があります。詳細は以下のブログエントリなどを参照ください。
MediaLiveのVPC InputにアタッチするSecurity Groupについては、Inbound ruleでMediaLive VPC Inputへの入力となるRTMPの1935
ポートへの通信を許可するよう設定します。IPアドレスによるアクセス制限を実施したいため、Streaming Softwareのアクセス元となるIPアドレスを通信許可対象として設定します。(後述しますが、この他にNLB Target GroupでのクライアントIPアドレス保持についても設定が必要です。)またNLBからのHealth Check用の通信を許可するため、使用するVPCのCIDR(10.100.0.0/16
)を通信許可対象のIPアドレスとして指定しました。(今回は使用するVPC全体を許可対象としましたが、より厳密に制御するのであれば、NLB配置のサブネットのみとすることも可能です。)Outbound ruleについてはデフォルトのままとしています。
MediaLiveでVPC Inputの作成
続いてMediaLiveでVPC Input(RTMPのVPC modeのInput)を作成します。MediaLiveのマネジメントコンソール、Inputsの画面の[Create input]ボタンで進みます。Input nameを適切に設定し(今回はrtmps-medialive-input
としました)、Input typeではRTMP (push)
を選択します。
Network modeではVPC
を選択します。VPC settingsの項目でSubnetとSecurity Groupを選択します。Subnetは構築済みのPrivate Subnet、Security Groupは先ほど作成したものですね。なおSubnet設定の箇所に「2つの異なるAZのSubnetを指定する」ように記載されていますが、後述のとおりInput classをSINGLE_INPUT
としてAZを1つのみ使用する設定であれば、1つののSubnetのみの指定でも問題ないようでした。
Input destinationsのInput class指定ではSINGLE_INPUT
を選択しました。後ほど作成するMediaLive ChannelのPipelineもSINGLE_PIPELINEを選択するようにします。今回は動作検証目的であるため、Pipelineの冗長性は不要としました。
MediaLiveのVPC Inputが作成できました。Endpointsに表示されているIPv4アドレスは後ほどNLB作成時に使用しますので控えておきましょう。Input security groupsの項目は空欄となっていますが、こちらはVPC ModeでないInputに対応するSecurity groupとなります。実際にこのVPC InputにアタッチされているSecurity Groupについては、Network interface IDをもとにEC2のマネジメントコンソールでNetwork Interfaceの詳細を参照することで確認することができます。
NLBの作成
MediaLiveのInputが作成できたので、続いてNLBの作成に進みます。まずTarget Groupを作成し、その後NLB本体の作成を行います。
Target Groupの作成
EC2のマネジメントコンソール、Target Groupsの項目の[Create target group]ボタンから進みます。Basic configrationではIP address
を指定します。
Target Group nameはrtmps-nlb-targetgroup
としました。このTarget GroupではRTMPSを受けるのではなく、TLS終端後のRTMPを扱いますのでProtocol:PortはTCP:1935
と設定します。VPCはMediaLive VPC Inputを作成したVPCを指定、Health checksの項目についてはデフォルトのまま、[Next]ボタンで次ページに進みます。
Register targetsの項目で、先ほど作成したMediaLive VPC InputのIPアドレスを入力します。その後[Include as pending below]ボタンを押下することでページ下部のTargetsに追加されます。
Target Groupが作成できました。
Attributesのタグを確認します。クライアントIPアドレスの保持機能が無効(Off)になっているので、こちらを有効(On)にしておきます。これでSecurity GroupでのIPアドレスによるアクセス制限が可能になります。
NLB本体
続いてNLB本体の作成です。マネジメントコンソールLoad Balancersのページから[Create Load Balancer]ボタンで進み、Network Load Balancerを選択します。
名称はrtmps-nlb
としました。SchemeはInternet-facing
、IP address typeはIPv4
で進みます。
Network mappingではMediaLive VPC Inputを作成したのと同じVPCを指定します。またSbunetについて、NLBについてはPublic Subnetに配置しますので該当のSubnetを指定します。
Listeners and routingの項目では、Protocol:PortでTLS:443
を指定します。ここでRTMPSを受け付けてTLS終端を行い、先ほど作成したTarget Group rtmps-nlb-targetgroup
にルーティングします。
Secure listener settingsの箇所、今回使用する独自ドメインに対応したACM証明書を指定します。(ACM証明書の取得などについては本エントリでは手順を省略します。)またALPN policyではHTTP2Preferred
を選択します。
作成できました。作成直後はStateがProvisioningですが、作成が完了するとActiveとなります。
Route 53でDNSレコード登録
今回作成したNLBを独自ドメインで利用するため、Route 53でDNSレコードを登録しておきます。Route 53のレコード登録画面でサブドメインを指定、Record typeはAレコードとしてAliasを設定します。A ALIASレコードの利用ですね。(CNAMEでの登録も可能ですが、A ALIASのほうがパフォーマンスがよく、コストも抑えることができます。)
Route traffic toの項目でNLBへのAliasを選択、該当のリージョン(今回はap-northeast-1)とNLB(先ほど作成したもの)を選択してDNSレコードを登録します。
MediaLiveのOutput以降のリソースの作成
本エントリの主題である「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」部分までの構築が終わりました。MediaLiveのOutput以降のリソースについては任意のものが利用可能となりますが、今回はMediaLiveのWorkflow wizardを使ってMediaPackage、CloudFrontのリソースを作成、HLSで実際にRTMPSで打ち上げた映像を視聴確認できるようにします。
MediaLiveのマネジメントコンソール、Workflow wizardの画面から[Create workflow]ボタンで進みます。Workflow nameはrtmps-medialive-workflow
としました。channel classはSINGLE_PIPELINE
を選択、IAM roleについても指定します。
input typeはRTMP (push)
を選択し、User an existing input
で作成済みのrtmps-medialive-input
を指定します。
OutputはMediaPackageを選択します。Channelを新規に作成し、Video renditionsは検証用途ですので720p30
の1つのみとしました。
Workflowが作成できました。
MediaLiveとNLBでRTMPSによるストリーミング環境を行う
Streaming Softwareから受け取ったRTMPSをTLS終端させるNLB、NLBからRTMPで映像を受け取るMediaLive、そして視聴用のリソース(MediaPackageとCloudFront)の作成ができました。それでは実際にStreaming SoftwareからRTMPSで映像を打ち上げて、ストリーミングでの映像視聴ができるか確認してみたいと思います。
MediaLive ChannelのStart
MediaLiveのWorkflow wizardでリソースを作成した直後は、Channelは停止しているIdleの状態です。
そのため、NLB Target GroupのHealth statusとしてもunhealthy
となりHealth Checkに失敗している状態となります。
WorkflowをStartさせます。(連動して、MediaLive ChannelがStartします。)それぞれがRunning
状態になり、その後NLB Target Groupを確認してみると、Health statusがhealthy
となり、Health Checkに成功していることが確認できます。これで準備完了です。
Streaming SoftwareからRTMPSで映像を打ち上げ
AWS側の準備ができたので、続いてStreaming SoftwareからRTMPSで映像を打ち上げます。Streaming Softwareとして、今回はiPhone XS上のZixi ONAIRを使用しました。RTMP SettingsのURLをrtmps://
ではじめることで、RTMPSを指定します。
打ち上げた映像のストリーミング視聴確認
実際にRTMPSで打ち上げた映像を、ストリーミング視聴してみます。今回はHLS形式で確認し、再生PlayerにはmacOS上のSafariブラウザを使用しました。
再生用EndpointをAWSマネジメントコンソールから確認していきます。MediaLive WorkflowのMediaPackage HLS Endpointの「Link to resource」に続くリンクをクリックして、MediaPackageの画面に遷移します。
CloudFront URLをコピーして、Safariブラウザで開きます。
問題なく視聴できていますね!
まとめ
AWS Media Blogで紹介されていた「RTMPSをNLBでTLS終端させて、RTMPとしてMediaLiveの入力とする」方法を、実際に構築して確認してみました。NLBそしてMediaLiveのVPC対応を上手に活用したソリューションだなと思います。MediaLive InputはVPC Modeである必要があること、VPC内での各リソースの配置、NLBがSecurity Groupを持たずMediaLive VPC InputにアタッチするSecurity GroupでIPアドレスなどのアクセス制限を行う必要があること、などに注意しておきましょう。
また今回は動作検証目的として、MediaLiveをSingle Pipeline構成、NLBも単一AZとしました。本番構成では冗長化が必須です。MediaLiveで冗長構成をとった際のNLB側の構成について、例えばMulti-AZ構成としたほうが良いのかなど、検討しておきたいと思いました。